<html>
 <head>
  <meta charset="UTF-8">
 </head>
 <body>
  <h1 data-lake-id="k8Nc0" id="k8Nc0"><span data-lake-id="u12b91bc0" id="u12b91bc0">典型回答</span></h1>
  <p data-lake-id="u00ee9707" id="u00ee9707"><br></p>
  <p data-lake-id="u55e8a2b6" id="u55e8a2b6"><span data-lake-id="u05477a03" id="u05477a03">以下代码中，在JDK 1.8中，JDK 11及以上版本中执行后结果不是一样的。</span></p>
  <p data-lake-id="u5db5c328" id="u5db5c328"><br></p>
  <pre lang="java"><code>
String s3 = new String("1") + new String("1");
s3.intern();
String s4 = "11";
System.out.println(s3 == s4);
</code></pre>
  <p data-lake-id="ufd4ad078" id="ufd4ad078"><br></p>
  <p data-lake-id="u64c042ed" id="u64c042ed"><span data-lake-id="uf8c7cd86" id="uf8c7cd86">你会发现，在JDK 1.8中，以上代码得到的结果是true，而JDK 11及以上的版本中结果却是false。</span></p>
  <p data-lake-id="ubb70dbb2" id="ubb70dbb2"><span data-lake-id="uc1ab9eca" id="uc1ab9eca">​</span><br></p>
  <p data-lake-id="u2733c683" id="u2733c683"><span data-lake-id="ua9ae7779" id="ua9ae7779">那么，再稍作修改呢？在目前的所有JDK版本中，执行以下代码：</span></p>
  <p data-lake-id="u0f68eedc" id="u0f68eedc"><span data-lake-id="uc52bb45b" id="uc52bb45b">​</span><br></p>
  <pre lang="java"><code>
String s3 = new String("3") + new String("3");// ①
s3.intern();// ②
String s4 = "33";
System.out.println(s3 == s4);// ③
</code></pre>
  <p data-lake-id="ue65df85a" id="ue65df85a"><br></p>
  <p data-lake-id="u6965426c" id="u6965426c"><span data-lake-id="u99180e50" id="u99180e50">得到的结果也是true，你知道为什么嘛？</span></p>
  <p data-lake-id="uba66c488" id="uba66c488"><span data-lake-id="ufaa99be1" id="ufaa99be1">​</span><br></p>
  <p data-lake-id="u048e6fd8" id="u048e6fd8"><span data-lake-id="ufa4ef23a" id="ufa4ef23a">看这篇文章之前，请先阅读以下文章，先确保自己了解了intern的原理！！！</span></p>
  <p data-lake-id="ud5cce444" id="ud5cce444"><span data-lake-id="u41eee0cb" id="u41eee0cb">​</span><br></p>
  <p data-lake-id="u330fe3dd" id="u330fe3dd"><span data-lake-id="u8fd3ae11" id="u8fd3ae11">​</span><br></p>
  <p data-lake-id="u182acfe7" id="u182acfe7"><span data-lake-id="u3ca7b762" id="u3ca7b762">出现上述现象，肯定是因为在JDK 11 及以上的版本中，"11"这个字面量已经被提前存入字符串池了。那什么时候存进去的呢？（这个问题，全网应该没人提过）</span></p>
  <p data-lake-id="u131a0c38" id="u131a0c38"><span data-lake-id="uca209709" id="uca209709">​</span><br></p>
  <p data-lake-id="u2bb1de56" id="u2bb1de56"><span data-lake-id="u8f544e6b" id="u8f544e6b">经过我七七四十九天的研究，终于发现了端倪，就在以下代码中：</span><a href="https://github.com/zxiaofan/JDK/blob/19a6c71e52f3ecd74e4a66be5d0d552ce7175531/jdk-11.0.2/src/jdk.compiler/com/sun/tools/javac/code/Source.java" target="_blank" data-lake-id="u74eb78da" id="u74eb78da"><span data-lake-id="ua5ab044e" id="ua5ab044e">Source.java</span></a></p>
  <p data-lake-id="ubf2e7795" id="ubf2e7795"><span data-lake-id="u7103a414" id="u7103a414">​</span><br></p>
  <pre lang="java"><code>
public enum Source {
    /** 1.0 had no inner classes, and so could not pass the JCK. */
    // public static final Source JDK1_0 =              new Source("1.0");

    /** 1.1 did not have strictfp, and so could not pass the JCK. */
    // public static final Source JDK1_1 =              new Source("1.1");

    /** 1.2 introduced strictfp. */
    JDK1_2("1.2"),

    /** 1.3 is the same language as 1.2. */
    JDK1_3("1.3"),

    /** 1.4 introduced assert. */
    JDK1_4("1.4"),

    /** 1.5 introduced generics, attributes, foreach, boxing, static import,
     *  covariant return, enums, varargs, et al. */
    JDK5("5"),

    /** 1.6 reports encoding problems as errors instead of warnings. */
    JDK6("6"),

    /** 1.7 introduced try-with-resources, multi-catch, string switch, etc. */
    JDK7("7"),

    /** 1.8 lambda expressions and default methods. */
    JDK8("8"),

    /** 1.9 modularity. */
    JDK9("9"),

    /** 1.10 local-variable type inference (var). */
    JDK10("10"),

    /** 1.11 covers the to be determined language features that will be added in JDK 11. */
    JDK11("11");
}
</code></pre>
  <p data-lake-id="u4fd23c3a" id="u4fd23c3a"><br></p>
  <p data-lake-id="uaa4b7a80" id="uaa4b7a80"><span data-lake-id="u720d5115" id="u720d5115">看到了么，xdm，在JDK 11 的源码中，定义了"11"这个字面量，那么他会提前进入到字符串池中，那么后续的intern的过程就会直接从字符串池中获取到这个字符串引用。</span></p>
  <p data-lake-id="u2f1c5899" id="u2f1c5899"><span data-lake-id="ua5d331a1" id="ua5d331a1">​</span><br></p>
  <p data-lake-id="udb249f7b" id="udb249f7b"><span data-lake-id="u6c19ac92" id="u6c19ac92">按照这个思路，大家可以在JDK 11中执行以下代码：</span></p>
  <p data-lake-id="u759c3a49" id="u759c3a49"><span data-lake-id="uaab6d5eb" id="uaab6d5eb">​</span><br></p>
  <pre lang="java"><code>
String s3 = new String("1") + new String("1");
s3.intern();
String s4 = "11";
System.out.println(s3 == s4);


String s3 = new String("1") + new String("2");
s3.intern();
String s4 = "12";
System.out.println(s3 == s4);
</code></pre>
  <p data-lake-id="u6fe79bb3" id="u6fe79bb3"><br></p>
  <p data-lake-id="ua189c1f0" id="ua189c1f0"><span data-lake-id="ud62dcb1b" id="ud62dcb1b">得到的结果就是false和true。</span></p>
  <p data-lake-id="u528068e0" id="u528068e0"><br></p>
  <p data-lake-id="u9eb919b5" id="u9eb919b5"><span data-lake-id="u23b12863" id="u23b12863">或者我是在JDK 21中分别执行了以下代码：</span></p>
  <p data-lake-id="u40e91482" id="u40e91482"><span data-lake-id="u3208a8a9" id="u3208a8a9">​</span><br></p>
  <pre lang="java"><code>
String s3 = new String("2") + new String("1");
s3.intern();
String s4 = "21";
System.out.println(s3 == s4);


String s3 = new String("2") + new String("2");
s3.intern();
String s4 = "22";
System.out.println(s3 == s4);
</code></pre>
  <p data-lake-id="u46fd7baf" id="u46fd7baf"><span data-lake-id="u4f5cc51f" id="u4f5cc51f">​</span><br></p>
  <p data-lake-id="u3d6e16fe" id="u3d6e16fe"><span data-lake-id="u34e3393b" id="u34e3393b">得到的结果就也是false和true。</span></p>
 </body>
</html>